package PDFd;

import PDFd.ClientLibrary.IRenderEngine;
import PDFd.ClientLibrary.RenderEngineFactory;
import PDFd.Instance.InstanceManager;
import PDFd.Instance.PDFdInstance;
import PDFd.Instance.PersistanceException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import  gen.R;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * The activity first started when the application loads. 
 * This is responsible for displaying the intial menu of "New" "Load" "Export", etc. 
 * 
 * Most of this is logic for creating new events. It becomes complex because the 'creation' of a document is done in another thread
 * and communication with the android UI from other threads is not thread safe.
 * @author mckaym
 *
 */
public class HomeActivity extends Activity {
	/**
	 * The progress dialog shown to the user when we are performing an activity in a thread
	 */
	ProgressDialog pd;
	/**
	 * The rendering engine we use to turn a PDF into a resource that we can manipulate.
	 */
	IRenderEngine re;
	/**
	 * The context for messages that are displayed to the user
	 */
	Context c;
	/**
	 * The instance manager responsible for persisting and retrieving saved documents
	 */
	InstanceManager im;
	/**
	 * This sets up the instance manager, registers the buttons for UI control
	 */
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.homeview);
		c = this;
		try {
			im = InstanceManager.getInstanceManager();
		} catch (PersistanceException e1) {
		}
		
		Button load = (Button) findViewById(R.id.load);
		Button existing = (Button) findViewById(R.id.existing);
		/**
		 * When the load button is clicked, switch to the FileBrowser to select a file
		 */
		load.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				try {
					Intent intent = new Intent("org.openintents.action.PICK_FILE");
					startActivityForResult(intent, 1);
				} catch(Exception e) {
					informUserOfError("Please ensure OI File Manager is installed correctly.");
				}
			}
		});

		existing.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				int size = im.instances.size();
				if(size == 0) {
	        		informUserOfError("No documents to select from )=");
				} else {
					CharSequence[] items = new CharSequence[im.instances.size()];
					for(int i = 0; i < im.instances.size(); i++) {
						items[i] = i+" :"+im.instances.get(i).getDisplayName();
					}
					
					AlertDialog.Builder builder = new AlertDialog.Builder(c);
					builder.setTitle("Select a document");
					builder.setItems(items, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int item) {
				            Message msg = acitivtySwitcherHandler.obtainMessage();
				            msg.obj =im.instances.get(item);
				            acitivtySwitcherHandler.sendMessage(msg);
						}
					});
					AlertDialog alert = builder.create();
					alert.show();
				}
			}
		});
	}
	/**
	 * This is so the user cannot go back to the loading screen
	 */
	public void onBackPressed() {
	}
	/**
	 * Switches to the main PDFdActivity with the given PDFdInstance.
	 */
	final Handler acitivtySwitcherHandler = new Handler() {
        public void handleMessage(Message msg) {
        	if(pd != null) {
        		pd.dismiss();
        		pd = null;
        	}
        	if (msg.obj == null || ((PDFdInstance) msg.obj).getRenderedAsPNG() == null ) {
        		informUserOfError("Document conversion has failed. Is the server running?");
        		} else {
    		Intent prefIntent = new Intent(c,PDFdActivity.class);
        		CanvasView.setPDFdInstance((PDFdInstance) msg.obj);
        		c.startActivity(prefIntent);
        	}
        }
	};

	//***** All code from here to the next comment is responsible for loading a new file
	/**
	 * Upon clicking a file in OI File Manager, the result is returned here.
	 * This spawns new thread in which a RenderEngine converts the selected file to a PNG
	 */
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if(data != null) {
        	Uri u = data.getData();
        	String p = u.getPath();
        	Log.i("URI: ", u.getPath());
        	PDFdInstance i = new PDFdInstance();
        	i.setDisplayName(p.substring(p.lastIndexOf("/")+1));
        	i.setPathToOriginalPDF(p);
        	
        	this.re = RenderEngineFactory.getEngine();
        	this.pd = ProgressDialog.show(this, "Opening PDF", "Starting...", true,false);
        	ConversionEngineThread t = new ConversionEngineThread(i);
        	Thread h = new Thread(t);
        	h.start();
        }
	}
	
	/**
	 * Can update the Progress Dialog with messages
	 */
	final Handler progressDialogHandler = new Handler() {
        public void handleMessage(Message msg) {
        	if(msg.arg1 == 0) {
        		pd.setMessage((String)msg.obj);
        	} else {
        		pd.dismiss();
        		informUserOfError((String)msg.obj);
        	}
        }
    };
    /**
     * Responsible for calling the render engine and notifying user of progress
     * This is in another thread because it may take a long time. if we do this the UI will freeze.
     * @author mckaym
     *
     */
	private class ConversionEngineThread implements Runnable {
		/**
		 * The PDFdInstance we're creating. This starts off empty, and fills it with data from the RenderEngine
		 */
		PDFdInstance pi;
		/**
		 * Helper method to send a message to the Progress Dialog
		 * @param message The message to put in the Progress Dialog
		 */
		private void sendMessage(String message) {
            Message msg = progressDialogHandler.obtainMessage();
            msg.obj = message;
            msg.arg1 = 0;
            progressDialogHandler.sendMessage(msg);
		}
		/**
		 * Abaondons this process. Closes the progess dialog, then displays the message to the user
		 * @param message The message to put in the notification dialog
		 */
		private void abandon(String message) {
            Message msg = progressDialogHandler.obtainMessage();
            msg.obj = message;
            msg.arg1 = 1;
            progressDialogHandler.sendMessage(msg);
		}

		public ConversionEngineThread(PDFdInstance pi) {
			this.pi = pi;
		}
		
		/**
		 * Converts the PDF into a Bitmap.
		 * Notfies the UI of what stage it is at
		 */
		public void run() {
            sendMessage("Reading PDF");
            Log.i("HomeActivity","Reading PDF!");
			System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");
            sendMessage("Uploading Document");
            try {
            	byte bytes[] = loadFile(pi.pathToOriginalPDF);
	            if(bytes == null) {
	            } else {
	            	String uuid = re.addPDF(bytes);
	            	if(uuid == null ) {
	            	} else {
	        			this.pi.setUUID(uuid);
	                    sendMessage("Converting Document (This may take up to 30 seconds)");
	        			byte convertedDocument[]  = re.getAsPNG(this.pi.getUUID(),10);
	        			if(convertedDocument == null) {
	        			} else {
	        				this.pi.setRenderedAsPNG(convertedDocument);
	        			}
	            	}
	            }
	            Message msg = acitivtySwitcherHandler.obtainMessage();
	            msg.obj = this.pi;
	            acitivtySwitcherHandler.sendMessage(msg);
            } catch (IOException e) {
                abandon("Unable to read file!");
            }
		}
		/**
		 * Helper method to load data from a file. We use this to load the PDF into a byte array to send to the render egine
		 * @param path path to the file
		 * @return Byte array representing the contents of the file
		 * @throws IOException
		 */
	    private byte[] loadFile(String path) throws IOException {
			File file = new File(path);
			InputStream is = null;
			is = new FileInputStream(file);
			long length = file.length();
			byte[] bytes = new byte[(int) length];
			int offset = 0;
			int numRead = 0;
			do {
				offset += numRead;
				if (offset >= bytes.length)
					break;
			} while ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0);
	    	return bytes;
	    }
	}
	public void informUserOfError(String message) {
		final AlertDialog alertDialog = new AlertDialog.Builder(HomeActivity.this).create();
		alertDialog.setTitle("WHOOPS");
		alertDialog.setMessage(message);
		alertDialog.setButton("Dismiss", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,int which) {
					alertDialog.dismiss();
				}
			});
		alertDialog.show();
		
	}
}